{#
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
 # http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#}
{% extends "manage_project_base.html" %}
{% set active_tab = "publishing" %}
{% block title %}{{ oidc_title() }}{% endblock %}
{% macro prefilled_warning() %}
  <div id="prefilled-warning" class="callout-block callout-block--warning">
    <h3 class="callout-block__heading">{% trans %}Proceed with caution!{% endtrans %}</h3>
    <p>
      {% trans %}Some form fields have been autofilled, please double-check their values before submitting the form.{% endtrans %}
    </p>
  </div>
{% endmacro %}
{% macro github_form(request, github_publisher_form) %}
  {{ prefilled_warning() if prefilled_provider == "github" }}
  <p>
    {% trans href="https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect" %}
    Read more about GitHub Actions' OpenID Connect support <a href="{{ href }}">here</a>.
  {% endtrans %}
</p>
{{ form_error_anchor(github_publisher_form) }}
<form id="github-publisher-form"
      method="post"
      action="{{ request.route_path('manage.project.settings.publishing', project_name=project.name) }}#errors">
  <input name="csrf_token"
         type="hidden"
         value="{{ request.session.get_csrf_token() }}">
  {{ form_errors(github_publisher_form) }}
  <div class="form-group">
    <label for="owner" class="form-group__label">
      {% trans %}Owner{% endtrans %}
      {% if github_publisher_form.owner.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% endif %}
    </label>
    {{ github_publisher_form.owner(placeholder=gettext("owner") , autocomplete="off", autocapitalize="off", spellcheck="false", class_="form-group__field", aria_describedby="owner-errors") }}
    <p class="form-group__help-text">
      {% trans %}The GitHub organization name or GitHub username that owns the repository{% endtrans %}
    </p>
    <div id="owner-errors">{{ field_errors(github_publisher_form.owner) }}</div>
  </div>
  <div class="form-group">
    <label for="repository" class="form-group__label">
      {% trans %}Repository name{% endtrans %}
      {% if github_publisher_form.repository.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% endif %}
    </label>
    {{ github_publisher_form.repository(placeholder=gettext("repository") ,
    autocomplete="off",
    autocapitalize="off",
    spellcheck="false",
    class_="form-group__field",
    aria_describedby="repository-errors",
    ) }}
    <p class="form-group__help-text">
      {% trans %}The name of the GitHub repository that contains the publishing workflow{% endtrans %}
    </p>
    <div id="repository-errors">{{ field_errors(github_publisher_form.repository) }}</div>
  </div>
  <div class="form-group">
    <label for="workflow_filename" class="form-group__label">
      {% trans %}Workflow name{% endtrans %}
      {% if github_publisher_form.workflow_filename.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% endif %}
    </label>
    {{ github_publisher_form.workflow_filename(placeholder=gettext("workflow.yml") ,
    class_="form-group__field",
    autocomplete="off",
    aria_describedby="workflow_filename-errors",
    ) }}
    <p class="form-group__help-text">
      {% trans %}The filename of the publishing workflow. This file should exist in the <code>.github/workflows/</code> directory in the repository configured above.{% endtrans %}
    </p>
    <div id="workflow_filename-errors">{{ field_errors(github_publisher_form.workflow_filename) }}</div>
  </div>
  <div class="form-group">
    <label for="environment" class="form-group__label">
      {% trans %}Environment name{% endtrans %}
      {% if github_publisher_form.environment.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% else %}
        <span class="form-group__required">{% trans %}(optional){% endtrans %}</span>
      {% endif %}
    </label>
    {{ github_publisher_form.environment(placeholder=gettext("release") ,
    class_="form-group__field",
    autocomplete="off",
    aria_describedby="environment-errors",
    ) }}
    <p class="form-group__help-text">
      {% trans href="https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment" %}
      The name of the <a href="{{ href }}">GitHub Actions environment</a>
      that the above workflow uses for publishing.  This should be
      configured under the repository's settings. While not required, a
      dedicated publishing environment is <strong>strongly</strong>
      encouraged, <strong>especially</strong> if your repository has
      maintainers with commit access who shouldn't have PyPI publishing
      access.
    {% endtrans %}
  </p>
  <div id="environment-errors">{{ field_errors(github_publisher_form.environment) }}</div>
</div>
<div>
  <input type="submit"
         value="{% trans %}Add{% endtrans %}"
         class="button button--primary">
</div>
</form>
{% endmacro %}
{% macro gitlab_form(request, gitlab_publisher_form) %}
  {{ prefilled_warning() if prefilled_provider == "gitlab" }}
  <p>
    {% trans href="https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html" %}
    Read more about GitLab CI/CD OpenID Connect support <a href="{{ href }}">here</a>.
  {% endtrans %}
</p>
{{ form_error_anchor(gitlab_publisher_form) }}
<form id="gitlab-publisher-form"
      method="post"
      action="{{ request.route_path('manage.project.settings.publishing', project_name=project.name) }}#errors">
  <input name="csrf_token"
         type="hidden"
         value="{{ request.session.get_csrf_token() }}">
  {{ form_errors(gitlab_publisher_form) }}
  <div class="form-group">
    <label for="namespace" class="form-group__label">
      {% trans %}Namespace{% endtrans %}
      {% if gitlab_publisher_form.namespace.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% endif %}
    </label>
    {{ gitlab_publisher_form.namespace(placeholder=gettext("namespace") , autocomplete="off", autocapitalize="off", spellcheck="false", class_="form-group__field", aria_describedby="namespace-errors") }}
    <p class="form-group__help-text">
      {% trans %}The GitLab username or GitLab group/subgroup namespace that the project is under{% endtrans %}
    </p>
    <div id="namespace-errors">{{ field_errors(gitlab_publisher_form.namespace) }}</div>
  </div>
  <div class="form-group">
    <label for="project" class="form-group__label">
      {% trans %}Project name{% endtrans %}
      {% if gitlab_publisher_form.project.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% endif %}
    </label>
    {{ gitlab_publisher_form.project(placeholder=gettext("project") , autocomplete="off", autocapitalize="off", spellcheck="false", class_="form-group__field", **{"aria-describedby":"project-errors"}) }}
    <p class="form-group__help-text">
      {% trans %}The name of the GitLab project that contains the publishing workflow{% endtrans %}
    </p>
    <div id="project-errors">{{ field_errors(gitlab_publisher_form.project) }}</div>
  </div>
  <div class="form-group">
    <label for="workflow_filepath" class="form-group__label">
      {% trans %}Top-level pipeline file path{% endtrans %}
      {% if gitlab_publisher_form.workflow_filepath.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% endif %}
    </label>
    {{ gitlab_publisher_form.workflow_filepath(placeholder=gettext(".gitlab-ci.yml") , class_="form-group__field", autocomplete="off", **{"aria-describedby":"workflow_filepath-errors"}) }}
    <p class="form-group__help-text">
      {% trans %}The file path of the top-level pipeline, relative to the project's root. This file should exist in the project configured above (external pipelines are not supported).{% endtrans %}
    </p>
    <div id="workflow_filepath-errors">{{ field_errors(gitlab_publisher_form.workflow_filepath) }}</div>
  </div>
  <div class="form-group">
    <label for="environment" class="form-group__label">
      {% trans %}Environment name{% endtrans %}
      {% if gitlab_publisher_form.environment.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% else %}
        <span class="form-group__required">{% trans %}(optional){% endtrans %}</span>
      {% endif %}
    </label>
    {{ gitlab_publisher_form.environment(placeholder=gettext("release") , class_="form-group__field", autocomplete="off", **{"aria-describedby":"environment-errors"}) }}
    <p class="form-group__help-text">
      {% trans href="https://docs.gitlab.com/ee/ci/environments/" %}
      The name of the <a href="{{ href }}">GitLab CI/CD environment</a>
      that the above workflow uses for publishing.  This should be
      configured under the project's settings. While not required, a
      dedicated publishing environment is <strong>strongly</strong>
      encouraged, <strong>especially</strong> if your project has
      maintainers with commit access who shouldn't have PyPI publishing
      access.
    {% endtrans %}
  </p>
  <div id="environment-errors">{{ field_errors(gitlab_publisher_form.environment) }}</div>
</div>
{% if gitlab_publisher_form.issuer_url.choices|length > 1 %}
  <div class="form-group">
    <label for="issuer_url" class="form-group__label">
      {% trans %}GitLab instance{% endtrans %}
      {% if gitlab_publisher_form.issuer_url.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% endif %}
    </label>
    {{ gitlab_publisher_form.issuer_url(class_="form-group__field", **{"aria-describedby":"issuer_url-errors"}) }}
    <p class="form-group__help-text">
      {% trans %}The GitLab instance URL. Select <code>https://gitlab.com</code> for the public GitLab service, or a custom instance.{% endtrans %}
    </p>
    <div id="issuer_url-errors">{{ field_errors(gitlab_publisher_form.issuer_url) }}</div>
  </div>
{% else %}
  {# The following field must be present for the view predicate to match #}
  {{ gitlab_publisher_form.issuer_url(hidden=True) }}
{% endif %}
<div>
  <input type="submit"
         value="{% trans %}Add{% endtrans %}"
         class="button button--primary">
</div>
</form>
{% endmacro %}
{% macro google_form(request, google_publisher_form) %}
  {{ prefilled_warning() if prefilled_provider == "google" }}
  <p>
    {% trans href="https://cloud.google.com/iam/docs/service-account-creds" %}
    Read more about Google's OpenID Connect support <a href="{{ href }}">here</a>.
  {% endtrans %}
</p>
{{ form_error_anchor(google_publisher_form) }}
<form id="google-publisher-form"
      method="post"
      action="{{ request.route_path('manage.project.settings.publishing', project_name=project.name) }}#errors">
  <input name="csrf_token"
         type="hidden"
         value="{{ request.session.get_csrf_token() }}">
  {{ form_errors(google_publisher_form) }}
  <div class="form-group">
    <label for="email" class="form-group__label">
      {% trans %}Email{% endtrans %}
      {% if google_publisher_form.email.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% endif %}
    </label>
    {{ google_publisher_form.email(placeholder=gettext("email") , autocomplete="off", autocapitalize="off", spellcheck="false", class_="form-group__field", aria_describedby="email-errors") }}
    <p class="form-group__help-text">
      {% trans %}The email address of the account or service account used to publish.{% endtrans %}
    </p>
    <div id="email-errors">{{ field_errors(google_publisher_form.email) }}</div>
  </div>
  <div class="form-group">
    <label for="subject" class="form-group__label">
      {% trans %}Subject{% endtrans %}
      {% if google_publisher_form.sub.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% else %}
        <span class="form-group__required">{% trans %}(optional){% endtrans %}</span>
      {% endif %}
    </label>
    {{ google_publisher_form.sub(placeholder=gettext("subject") ,
    autocomplete="off",
    autocapitalize="off",
    spellcheck="false",
    class_="form-group__field",
    aria_describedby="sub-errors",
    ) }}
    <p class="form-group__help-text">
      {% trans href="https://cloud.google.com/docs/authentication/token-types#id-contents" %}The subject is the numeric ID that represents the principal making the request. While not required, providing the subject further restricts the identity which is used for publishing. <a href="{{ href }}">More details here.</a>{% endtrans %}
    </p>
    <div id="sub-errors">{{ field_errors(google_publisher_form.sub) }}</div>
  </div>
  <div>
    <input type="submit"
           value="{% trans %}Add{% endtrans %}"
           class="button button--primary">
  </div>
</form>
{% endmacro %}
{% macro activestate_form(request, activestate_pubisher_form) %}
  {{ prefilled_warning() if prefilled_provider == "activestate" }}
  <p>
    {% trans href="https://docs.activestate.com/platform/user/oidc/" %}
    Read more about ActiveState's OpenID Connect support <a href="{{ href }}">here</a>.
  {% endtrans %}
</p>
{{ form_error_anchor(activestate_pubisher_form) }}
<form id="activestate-publisher-form"
      method="post"
      action="{{ request.route_path('manage.project.settings.publishing', project_name=project.name) }}#errors">
  <input name="csrf_token"
         type="hidden"
         value="{{ request.session.get_csrf_token() }}">
  {{ form_errors(activestate_pubisher_form) }}
  <div class="form-group">
    <label for="organization" class="form-group__label">
      {% trans %}Organization{% endtrans %}
      {% if activestate_pubisher_form.organization.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% endif %}
    </label>
    {{ activestate_pubisher_form.organization(placeholder=gettext("my-organization") ,
    autocomplete="off",
    autocapitalize="off",
    spellcheck="false",
    class_="form-group__field",
    aria_describedby="organization-errors")
    }}
    <p class="form-group__help-text">{% trans %}The ActiveState organization name that owns the project{% endtrans %}</p>
    <div id="organization-errors">{{ field_errors(activestate_pubisher_form.organization) }}</div>
  </div>
  <div class="form-group">
    <label for="project" class="form-group__label">
      {% trans %}ActiveState Project name{% endtrans %}
      {% if activestate_pubisher_form.project.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% endif %}
    </label>
    {{ activestate_pubisher_form.project(placeholder=gettext("my-project") ,
    autocomplete="off",
    autocapitalize="off",
    spellcheck="false",
    class_="form-group__field",
    aria_describedby="project-errors")
    }}
    <p class="form-group__help-text">
      {% trans %}The ActiveState project that will build your Python artifact.{% endtrans %}
    </p>
    <div id="project-errors">{{ field_errors(activestate_pubisher_form.project) }}</div>
  </div>
  <div class="form-group">
    <label for="actor" class="form-group__label">
      {% trans %}Actor Username{% endtrans %}
      {% if activestate_pubisher_form.actor.flags.required %}
        <span class="form-group__required">{% trans %}(required){% endtrans %}</span>
      {% endif %}
    </label>
    {{ activestate_pubisher_form.actor(placeholder=gettext("my-username") ,
    class_="form-group__field",
    autocomplete="off",
    aria_describedby="actor-errors")
    }}
    <p class="form-group__help-text">
      {% trans %}The username for the ActiveState account that will trigger the build of your Python artifact.{% endtrans %}
    </p>
    <div id="actor-errors">{{ field_errors(activestate_pubisher_form.actor) }}</div>
  </div>
  <div>
    <input type="submit"
           value="{% trans %}Add{% endtrans %}"
           class="button button--primary">
  </div>
</form>
{% endmacro %}
{% block main %}
  {% if testPyPI %}
    {% set title = "TestPyPI" %}
  {% else %}
    {% set title = "PyPI" %}
  {% endif %}
  <div class="horizontal-section">
    <div class="site-container">
      <section>
        <h1 class="page-title">{{ oidc_title() }}</h1>
        {{ oidc_desc() }}
        <h2>{% trans %}Manage current publishers{% endtrans %}</h2>
        {% if project.oidc_publishers %}
          <table class="table table--publisher-list">
            <caption class="sr-only">
              {% trans project_name=project.name %}OpenID Connect publishers associated with {{ project_name }}{% endtrans %}
            </caption>
            <thead>
              <tr>
                <th scope="col">{% trans %}Publisher{% endtrans %}</th>
                <th scope="col">{% trans %}Details{% endtrans %}</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {% for publisher in project.oidc_publishers %}{{ oidc_publisher_row(publisher) }}{% endfor %}
            </tbody>
          </table>
        {% else %}
          <p class="no-bottom-padding">{% trans %}No publishers are currently configured.{% endtrans %}</p>
        {% endif %}
      </section>
      <section>
        <h2 class="no-bottom-padding">{% trans %}Add a new publisher{% endtrans %}</h2>
        {% if request.user.has_two_factor %}
          {% set publishers = [
                      ("GitHub", github_form(request, github_publisher_form)),
                      ("GitLab", gitlab_form(request, gitlab_publisher_form)),
                      ("Google", google_form(request, google_publisher_form)),
                      ("ActiveState", activestate_form(request, activestate_publisher_form)),
                    ] %}
          <div class="horizontal-tabs"
               data-controller="horizontal-tabs"
               data-horizontal-tabs-index="0">
            <div class="horizontal-tabs__tabbar">
              {% for publisher_name, _ in publishers %}
                {% if not disabled[publisher_name] %}
                  <button data-horizontal-tabs-target="{{ 'tab prefilledTab' if publisher_name.lower() == prefilled_provider else 'tab' }}"
                          data-action="horizontal-tabs#change"
                          class="tab {{ "is-active" if loop.first else "" }}">{{ publisher_name }}</button>
                {% endif %}
              {% endfor %}
            </div>
            {% for publisher_name, publisher_form in publishers %}
              {% if not disabled[publisher_name] %}
                <div class="horizontal-tabs__tabcontent {{ "is-hidden" if loop.first else "" }}"
                     data-horizontal-tabs-target="tabPanel">{{ publisher_form }}</div>
              {% endif %}
            {% endfor %}
          </div>
        {% else %}
          {# user has not enabled 2FA #}
          <div class="callout-block callout-block--warning">
            {% trans href=request.route_path('manage.account.two-factor') %}
            You must first enable <a href="{{ href }}">two-factor authentication</a> on your account before adding a new publisher.
          {% endtrans %}
        </div>
      {% endif %}
    </section>
  </div>
</div>
{# Define the modal for constraining environments only if the expected URL params are present -#}
{% if request.params.constrained_environment_name is defined and request.params.constrained_publisher_id is defined %}
  {% set title = gettext("Constrain environment") %}
  {% set constrained_environment_name = request.params.constrained_environment_name %}
  {% set confirm_name = "constrain_environment" %}
  {% set confirm_button_label = gettext("Constrain environment") %}
  {% set slug = confirm_name.lower().replace(' ', '-') + '-modal' %}
  {% set extra_fields %}
    <input name="constrained_publisher_id"
           type="hidden"
           value="{{ request.params.constrained_publisher_id }}">
    <input name="constrained_environment_name"
           type="hidden"
           value="{{ constrained_environment_name }}">
  {% endset %}
  {% set extra_description %}
    <div>
      <div>
        {% trans %}This will restrict the Trusted Publisher's environment to{% endtrans %} <strong>{{ constrained_environment_name }}</strong>.
      </div>
      <div class="callout-block callout-block--warning">
        {% trans %}
        If you currently use multiple environments in your CI/CD workflows, you
        must either change them all to '{{ constrained_environment_name }}' or register
        each as a Trusted Publisher.
      {% endtrans %}
    </div>
    <ul class="no-bullets no-left-margin">
      <li>
        <input class="inline-checkbox"
               type="checkbox"
               data-action="input->confirm#check"
               data-confirm-target="checkbox">
        {% trans %}I understand that this Trusted Publisher will only allow uploads from CI/CD workflows running in the '{{ constrained_environment_name }}' environment.{% endtrans %}
      </li>
    </ul>
  </div>
{% endset %}
{{ confirm_modal(title=title, label=gettext("New Environment Name") , confirm_name="constrained_environment_name", confirm_string=constrained_environment_name, slug=slug, confirm_button_label=confirm_button_label, extra_fields=extra_fields, extra_description=extra_description, warning=False, confirm_string_in_title=False) }}
{% endif %}
{% endblock %}
